/*
 * Created on 04/08/2010
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package exec;



import graphic.Turtle;

public class Executor {

	final private int 
		SOBE = 1,
		DESCE = 2,
		FRENTE = 3,
		TRAS = 4,
		DIR = 5,
		ESQ = 6,
		HOME = 7,
		ASK = 8,
		ATRIB = 9,
		REPETE = 10,
		MAIS = 11,
		MENOS = 12,
		VEZES = 13,
		DIV = 14,
		MOD = 15,
		NUMERO = 16,
		VAR = 17,
		FIM_EXPR = Integer.MIN_VALUE;
	
	private int[] vector = new int[4096];
	private int last = 0;
	private Turtle tt;

	private int[] vars = new int[100];
	
	public Executor()
	{
	}
	
	public void setTurtle(Turtle t)
	{
		tt = t;
	}
	
	public void addSobe() {
		vector[last++] = SOBE;
	}

	public void addDesce() {
		vector[last++] = DESCE;
	}

	public void addFrente() {
		vector[last++] = FRENTE;
		
	}

	public void fimExpre() {
		vector[last++] = FIM_EXPR;
	}

	public void addTras() {
		vector[last++] = TRAS;
	}

	public void addDir() {
		vector[last++] = DIR;
	}

	public void addEsq() {
		vector[last++] = ESQ;
	}

	public void addCasa() {
		vector[last++] = HOME;
	}

	public void addPergunta(int i) {
		vector[last++] = ASK;
		vector[last++] = i;
	}

	public void addAtrib(int i) {
		vector[last++] = ATRIB;
		vector[last++] = i;
	}

	public int addRepete() {
		int k = last;
		vector[last++] = REPETE;
		vector[last++] = 0;
		return k;
	}

	public void fimRepete(int k) {
		vector[k+1] = last;
	}

	public void addExprMult() {
		vector[last++] = VEZES;
	}

	public void addExprMod() {
		vector[last++] = MOD;
	}

	public void addExprMais() {
		vector[last++] = MAIS;
	}

	public void addExprMenos() {
		vector[last++] = MENOS;
	}

	public void addExprDiv() {
		vector[last++] = DIV;
	}

	public void addExprNumero(String image) {
		int k = Integer.parseInt(image);
		vector[last++] = NUMERO;
		vector[last++] = k;
	}

	public void addExprVar(int i) {
		vector[last++] = VAR;
		vector[last++] = i;
	}

	
	public void executa(int inic, int fim)
	{
		int k = inic;
		while ( k < fim )
		{
			int op = vector[k];
			switch (op)
			{
				case SOBE:
					tt.up();
					break;
				case DESCE:
					tt.down();
					break;
				case FRENTE:
					int r = execExpr(k+1);
					tt.move(r);
					while (vector[k] != FIM_EXPR ) k++;
					break;
				case TRAS:
					r = execExpr(k+1);
					tt.move(-r);
					while (vector[k] != FIM_EXPR ) k++;
					break;
				case HOME:
					tt.go(0,0);
					tt.setAngle(0);
					break;
				case DIR:
					r = execExpr(k+1);
					while (vector[k] != FIM_EXPR ) k++;
					tt.setAngle(tt.getAngle()+r);
					break;
				case ESQ:
					r = execExpr(k+1);
					while (vector[k] != FIM_EXPR ) k++;
					tt.setAngle(tt.getAngle()-r);
					break;
				case ASK:
					r = tt.ask();
					vars[vector[k+1]] = r;
					k ++;
					break;
				case ATRIB:
					r = execExpr(k+2);
					vars [vector[k+1]] = r;
					while (vector[k] != FIM_EXPR ) k++;
					break;
				case REPETE:
					int l = vector[k+1];
					r = execExpr(k+2);
					while (vector[k] != FIM_EXPR ) k++;
					while ( r-- > 0 )
						executa(k, l);
					k = l-1;
					break;
			}
			k++;
		}
	}

	private int execExpr(int i) {
		int[] pilha = new int[20];
		int tp = 0;
		while ( vector[i] != FIM_EXPR )
		{
			switch (vector[i] )
			{
			case VAR:
				i++;
				pilha[tp++] = vars[vector[i++]];
				break;
			case NUMERO:
				i++;
				pilha[tp++] = vector[i++];
				break;
			case MAIS:
				i++;
				int r = pilha[tp-2] + pilha[tp-1];
				pilha[tp-2] = r;
				tp -= 2;
				break;
			case MENOS:
				i++;
				r = pilha[tp-2] - pilha[tp-1];
				pilha[tp-2] = r;
				tp -= 2;
				break;
			case VEZES:
				i++;
				r = pilha[tp-2] * pilha[tp-1];
				pilha[tp-2] = r;
				tp -= 2;
				break;
			case DIV:
				i++;
				r = pilha[tp-2] / pilha[tp-1];
				pilha[tp-2] = r;
				tp -= 2;
				break;
			case MOD:
				i++;
				r = pilha[tp-2] % pilha[tp-1];
				pilha[tp-2] = r;
				tp -= 2;
				break;
			}
		}
		return pilha[0];
	}

	public void executa() {
		executa(0,last);
	}
	
	


}
